package Server;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;

import Tools.Log;
import XML.XMLNode;

/**
 * 服务端监听类 主要接待客户，并封装成线程，同时触发客户进入事件
 * 
 * @author Sky.Wind
 * 
 */
public class Server extends ServerSocket implements Runnable, ServerListener {
	private Thread AcceptThread;// 监听线程
	protected volatile ConcurrentHashMap<Long, ClientThread> clientTidCache = new ConcurrentHashMap<Long, ClientThread>();// 客户缓存
	protected volatile ConcurrentHashMap<String, ClientThread> clientUidCache = new ConcurrentHashMap<String, ClientThread>();// 客户缓存
	// ，
	// 加速查找
	protected volatile LinkedList<ServerListener> listeners = new LinkedList<ServerListener>();// 监听器池

	/**
	 * 服务端构造方法
	 * 
	 * @param port
	 * @throws IOException
	 */
	public Server(int port) throws IOException {
		super(port, 1024, InetAddress.getByName("0.0.0.0"));
		this.setReuseAddress(true);
		this.setReceiveBufferSize(64 * 1024 * 1024);
		AcceptThread = new Thread(this);
		AcceptThread.start();// 启动客户监听线程
		addListener(this);
	}

	@Override
	public void accepClientEvent(ClientAcceptEvent ace) {
		clientTidCache.put(ace.getCt().getId(), ace.getCt());
		clientUidCache.put(ace.getCt().getName(), ace.getCt());
	}

	/**
	 * 注册监听器
	 * 
	 * @param cl
	 */
	public void addListener(ServerListener cl) {
		listeners.add(cl);
	}

	@Override
	public void ClientCloseEvent(ClientExitEvent cce) {
		clientTidCache.remove(cce.getCt().getId());
		clientUidCache.remove(cce.getCt().getName());
	}

	@Override
	public void ClientException(ClientException e) {

	}

	/**
	 * 查找客户
	 * 
	 * @param hashcode
	 * @return
	 */
	public ClientThread getClientThread(long tid) {
		return clientTidCache.get(tid);
	}

	/**
	 * 查找客户
	 * 
	 * @param userid
	 * @return
	 */
	public ClientThread getClientThread(String userid) {
		return clientUidCache.get(userid);
	}

	/**
	 * 事件触发入口（击鼓传花）
	 * 
	 * @param ce
	 */
	void informEvent(ClientEvent ce) {
		for (int i = 0; i < listeners.size(); i++) {
			if (ce instanceof ClientRequestEvent) {
				listeners.get(i).requestEvent((ClientRequestEvent) ce); // 客户请求事件
			} else if (ce instanceof ClientAcceptEvent) {
				listeners.get(i).accepClientEvent((ClientAcceptEvent) ce); // 客户进入事件
			} else if (ce instanceof ClientExitEvent) {
				listeners.get(i).ClientCloseEvent((ClientExitEvent) ce); // 客户离开事件
			} else if (ce instanceof ClientException) {
				listeners.get(i).ClientException((ClientException) ce); // 客户离开事件
			}
		}

	}

	/**
	 * 注销监听器
	 * 
	 * @param cl
	 */
	public void removeListener(ServerListener cl) {
		listeners.remove(cl);
	}

	@Override
	public void requestEvent(ClientRequestEvent se) {

	}

	/**
	 * 客户监听线程
	 */
	@Override
	public void run() {
		try {
			ClientThread ct;
			ClientAcceptEvent ace;
			while (true) {
				// /////////////////////
				ct = newClientThread(accept(), this); // 创建客户连接线程
				ace = new ClientAcceptEvent(this, ct);
				informEvent(ace); // 触发客户进入事件
				// //////////////////////
			}
		} catch (IOException e) {
			Log.print("accept:客户监听线程异常！");
		}
	}

	protected ClientThread newClientThread(Socket client, Server server) throws IOException {
		return new ClientThread(client, server);
	}

	/**
	 * 线程哈戏码定向发送数据
	 * 
	 * @param code
	 * @param cmd
	 * @return
	 */
	public boolean sendMessage(long tid, XMLNode cmd) {
		ClientThread ct = getClientThread(tid);
		if (ct != null) {
			ct.sendMessage(cmd);
			return true;
		}
		return false;
	}

	public boolean sendMessage(String UserName, XMLNode xmlnode) {
		ClientThread ct = getClientThread(UserName);
		if (ct != null) {
			ct.sendMessage(xmlnode);
			return true;
		}
		return false;
	}

}